package com.swt.gap.common.graph;

import lombok.extern.slf4j.Slf4j;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 请填写说明
 *
 * @author sx
 * @date 2020/8/12 21:16
 */
@Slf4j
@Component
public class Neo4jTools {

    private final EmbeddedNeo4j embeddedNeo4j;

    public Neo4jTools(EmbeddedNeo4j embeddedNeo4j) {
        this.embeddedNeo4j = embeddedNeo4j;
    }

    public Result executeCypher(String cypher) {
        Result result;
        GraphDatabaseService graphDatabaseService = embeddedNeo4j.getGraphDatabaseService();
        try (Transaction tx = graphDatabaseService.beginTx()) {
            result = graphDatabaseService.execute(cypher);
            tx.success();
        }
        return result;
    }

    public void executeCypherNoReturn(String cypher) {
        GraphDatabaseService graphDatabaseService = embeddedNeo4j.getGraphDatabaseService();
        try (Transaction tx = graphDatabaseService.beginTx()) {
            Result result = graphDatabaseService.execute(cypher);
            tx.success();
        }
    }

    /**
     * 根据cypher语句获取 一个返回值，return对象别名必须为 res
     * @param cypher return 的别名必须为res的cypher语句
     * @return List<Object>
     * @author sx
     */
    public List<Object> getOneResultByCypher(String cypher) {
        List<Object> retValue = new ArrayList<>();
        GraphDatabaseService graphDatabaseService = embeddedNeo4j.getGraphDatabaseService();
        try (Transaction tx = graphDatabaseService.beginTx()) {
            Result result = graphDatabaseService.execute(cypher);
            result.forEachRemaining(res -> {
                Optional.ofNullable(res.get("res")).ifPresent(retValue::add);
            });
            tx.success();
        }
        return retValue;
    }

    /**
     * 根据cypher语句获取 两个返回值 return对象别名必须为 res1,res2
     * @param cypher return 的别名必须为propertyValue的cypher语句
     * @return List<Object> 按顺序add，解析结果时按顺序获取
     * @author sx
     */
    public List<Object> getTwoResultByCypher(String cypher) {
        List<Object> retValue = new ArrayList<>();
        GraphDatabaseService graphDatabaseService = embeddedNeo4j.getGraphDatabaseService();
        try (Transaction tx = graphDatabaseService.beginTx()) {
            Result result = graphDatabaseService.execute(cypher);
            result.forEachRemaining(res -> {
                retValue.add(res.get("res1"));
                retValue.add(res.get("res2"));
            });
            return retValue;
        }
    }

    /**
     * 根据cypher语句获取 三个返回值 return对象别名必须为 res1,res2,res3
     * @param cypher return 的别名必须为propertyValue的cypher语句
     * @return List<Object> 按顺序add，解析结果时按顺序获取
     * @author sx
     */
    public List<Object> getThreeResultByCypher(String cypher) {
        List<Object> retValue = new ArrayList<>();
        GraphDatabaseService graphDatabaseService = embeddedNeo4j.getGraphDatabaseService();
        try (Transaction tx = graphDatabaseService.beginTx()) {
            Result result = graphDatabaseService.execute(cypher);
            result.forEachRemaining(res -> {
                retValue.add(res.get("res1"));
                retValue.add(res.get("res2"));
                retValue.add(res.get("res3"));
            });
            return retValue;
        }
    }
}
